package com.rytx.system.refund;

import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.rytx.common.core.domain.AjaxResult;
import com.rytx.system.domain.ArtOrderAfter;
import com.rytx.system.domain.ysp.ArtOrder;
import com.rytx.system.domain.ysp.ArtRental;
import com.rytx.system.mapper.ArtOrderAfterMapper;
import com.rytx.system.mapper.ArtOrderMapper;
import com.rytx.system.mapper.ArtRentalMapper;
import com.rytx.system.service.IArtAfterLogService;
import com.rytx.system.service.IArtOrderAfterService;
import com.rytx.system.service.impl.ArtOrderServiceImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;

/**
 * 租赁订单售后退款处理
 * */
@Component
public class LeaseAfterRefund implements IAfterRefund{
    @Autowired
    private ArtOrderServiceImpl artOrderService;
    @Autowired
    private ArtOrderMapper artOrderMapper;
    @Autowired
    private IArtOrderAfterService artOrderAfterService;//售后表
    @Autowired
    private IArtAfterLogService artAfterLogService;//操作记录表
    @Autowired
    private ArtRentalMapper artRentalMapper;


    //执行售后逻辑
    @Override
    public AjaxResult afterRefund(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        //补偿金额 和 退款金额 的计算逻辑 基于 首单当时扣款 续租订单在下期开始时扣款（例如： 首【当时扣】，第一次续租【暂时不扣款，第二次续租【扣第一次续租的款】）
        AjaxResult result = AjaxResult.success();
        //租赁订单售后退款处理逻辑
        //1.得到补偿金额
        BigDecimal compensationAmount = new BigDecimal(artOrderAfter.getCompensationAmount());



        /*
        一、仅退款
        普通支付的直接退款，免押的直接解冻

        二、退货退款和归还
        1、计算订单剩余金额，如果是退货退款，订单剩余金额就订单商品的总价，如果是归还的就是真正的订单剩余金额
        1.1、归还的订单剩余金额计算逻辑如下：
        1.1.1、如果是普通支付的租赁订单，订单剩余金额=订单商品总价-已使用金额
        1.1.2、如果是免押租赁的订单，如果是免押租赁的订单，先计算当前订单的剩余冻结金额（订单剩余金额=订单商品总价-已使用金额），并且查询剩余的冻结金额，先看看是不是一致，如果不一致记录异常（售后订单状态改成剩余金额异常状态），就不往下走了

        2.1、判断补偿金额大于订单剩余金额，给后台提示订单剩余金额还有多少钱
        2.2、否则，就退款或者解冻，逻辑如下：
        2.2.1、如果是普通支付的租赁订单，直接退款，退款金额=订单剩余金额-补偿金额
        2.2.2、如果是免押租赁的订单，扣款加解冻，扣款金额=补偿金额，解冻金额=剩余冻结金额-补偿金额
         */

        // 一、仅退款
        if(artOrderAfter.getAfterType() == 4){
            artOrder.setRefundAmount(artOrder.getFreezeAmount()); // 租赁订单，退款金额为冻结金额
            artOrderAfter.setRefundMoney(artOrder.getFreezeAmount().toString());
            refund(artOrderAfter, artOrder);
            artOrderService.afterZmnRefund(artOrder.getOrderNo());
        }

        // 二、退货退款和归还
        if(artOrderAfter.getAfterType() == 1 || artOrderAfter.getAfterType() == 2){
            ArtRental artRental = artRentalMapper.getTotalRentalFeeByIds(artOrder.getCartRentalIds());

            // 1、统一计算订单剩余金额，如果是退货退款，订单剩余金额就订单商品的总价，如果是归还的就是真正的订单剩余金额
            BigDecimal remainingAmount = new BigDecimal("0"); // 剩余金额
            if(artOrderAfter.getAfterType() == 1){//退货退款
                remainingAmount = artRental.getPrice();
            }else if(artOrderAfter.getAfterType() == 2){//归还
                // 1.1.1、如果是普通支付的租赁订单，订单剩余金额=订单商品总价-已使用金额，这里计算的订单剩余金额在免押订单也要使用
                // 计算已使用金额
                BigDecimal usedAmount = artOrder.getOrderAmount();
                // 查询主订单下的所有子订单，把子订单的金额加到已使用金额中
                List<ArtOrder> childOrderNos = artOrderMapper.getChildOrderNos(artOrder.getOrderNo());
                for (ArtOrder childOrder : childOrderNos){
                    usedAmount = usedAmount.add(childOrder.getOrderAmount());
                }
                // 订单剩余金额=订单商品总价-已使用金额
                remainingAmount = artRental.getPrice().subtract(usedAmount);

                if(artOrder.getZmAuthOrderNo() != null){
                    // 1.1.2、如果是免押租赁的订单，如果是免押租赁的订单，先计算当前订单的剩余冻结金额（订单剩余金额=订单商品总价-已使用金额），并且查询剩余的冻结金额，
                    // 先看看是不是一致，如果不一致记录异常（售后订单状态改成剩余金额异常状态），就不往下走了
                    // 查询免押订单剩余的冻结金额
                    String zmOrderString = artOrderService.zmnDetail(artOrder);
                    JSONObject zmOrder = JSONObject.parseObject(zmOrderString).getJSONObject("alipay_fund_auth_operation_detail_query_response");
                    if(zmOrder.getString("code").equals("10000")) {
                        // 订单当前剩余冻结金额，单位为：元
                        String restAmount = zmOrder.getString("rest_amount");
                        if(!restAmount.equals(remainingAmount.toString())) {
                            artOrderAfter.setStatus(23l); // 23-售后订单状态改成剩余金额异常状态
                            artOrderAfterService.updateArtOrderAfter(artOrderAfter);
                            artAfterLogService.createAfterLog(artOrderAfter.getPlatAfterNo(),
                                    "租赁订单售后解冻订单异常",
                                    artOrderAfter.getUserId(),
                                    IArtAfterLogService.SYSTEM_USER_TYPE_SYS,
                                    IArtAfterLogService.ORDER_STATUS_FINISH);
                            throw new RuntimeException("免押订单剩余冻结金额(" + restAmount + ")与计算得到的订单剩余金额(" + remainingAmount.toString() + ")不一致，需要人工处理");
                        }
                    }
                }

                // 2.1、判断补偿金额大于订单剩余金额，给后台提示订单剩余金额还有多少钱
                if(compensationAmount.compareTo(remainingAmount) > 0){
                    throw new RuntimeException("补偿金额大于订单剩余金额，目前订单剩余金额为：" + remainingAmount.toString());
                }

                // 计算应退款或者解冻的金额=订单剩余金额-补偿金额
                remainingAmount = remainingAmount.subtract(compensationAmount);
            }

            artOrderAfter.setRefundMoney(remainingAmount.toString());
            saveAfterRefundRecord(artOrderAfter, artOrder); // 保存售后记录

            artOrder.setRefundAmount(remainingAmount); // 保存退款金额

            // 2.2 就退款或者解冻
            if(artOrder.getZmAuthOrderNo() == null){ // 非免押订单，退款
                // 2.2.1、如果是普通支付的租赁订单，直接退款，退款金额=订单剩余金额-补偿金额
                refund(artOrderAfter, artOrder);
                artOrderService.afterZmnRefund(artOrder.getOrderNo());
            }else{
                // 2.2.2、如果是免押租赁的订单，扣款加解冻，扣款金额=补偿金额，解冻金额=剩余冻结金额-补偿金额
                // 先扣款
                boolean deduct = artOrderService.zmChargebacksCPAM(compensationAmount.toString(), artOrder);
                if(deduct){
                    // 扣款成功，解冻
                    AjaxResult ajaxResult = artOrderService.completeZmOrder(artOrder);
                }
            }
        }

        saveAfterRefundRecord(artOrderAfter, artOrder);

        return AjaxResult.success();
    }
    //计算补偿金额
    @Override
    public BigDecimal getCompensationAmount(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        String parentOrderNo = artOrder.getParentOrderNo();
        BigDecimal subtract = new BigDecimal(0);

        if(StringUtil.isEmpty(parentOrderNo)){//如果没有父订单号，说明是首单
            // String rest_amount = artOrderService.getRest_amount(artOrder.getOrderNo());
            BigDecimal freezeAmount = artOrder.getFreezeAmount();
            /* BigDecimal rest_amountBig = new BigDecimal(freezeAmount);//剩余金额*/

            BigDecimal compensationAmount = new BigDecimal(artOrderAfter.getCompensationAmount()) ;
            //补偿金额不能大于剩余金额
            /*if(compensationAmount.compareTo(freezeAmount) > 0){
                throw new RuntimeException("补偿金额大于商品金额");
            }*/
            BigDecimal orderAmount = artOrder.getOrderAmount();//订单金额
            //比较订单金额和补偿金额，如果补偿金额大于订单金额，则退款金额为 0 补偿金额为 补偿金额 - 订单金额 =实际要扣的补偿金额
            //因为退款金额 如果是首单的话 是 补偿金额如果大于订单金额 那么就不退款，所以这边把补偿金额减去订单金额
            if(compensationAmount.compareTo(orderAmount) > 0){
                subtract = compensationAmount.subtract(orderAmount);
            }else{//首单 如果补偿金额小于订单金额 那么补偿金额 就是0 因为在退款金额计算时已经减掉了补偿金额
                subtract =  new BigDecimal("0");
            }

            //如果是正常归还
            Long afterType = artOrderAfter.getAfterType();
            if(2 == afterType.longValue()){//首单正常归还-不退款
               /* String rest_amount = artOrderService.getRest_amount(artOrder.getOrderNo());
                BigDecimal rest_amountBig = new BigDecimal(rest_amount);//剩余金额
                compensationAmount =new BigDecimal(artOrderAfter.getCompensationAmount()) ;*/

                //补偿金额不能大于剩余金额
                /*if(compensationAmount.compareTo(rest_amountBig) > 0){
                    throw new RuntimeException("补偿金额大于冻结金额");
                }*/
                //由于正常归还的退款金额为0 所以这边首单计算补偿金额时 补偿金额就时填写的补偿金额

                subtract =compensationAmount;

            }
        }else{
            //   String rest_amount = artOrderService.getRest_amount(artOrder.getOrderNo());
            //  BigDecimal rest_amountBig = new BigDecimal(rest_amount);//剩余金额
            BigDecimal compensationAmount =new BigDecimal(artOrderAfter.getCompensationAmount()) ;
            Long afterType = artOrderAfter.getAfterType();
            if(2 == afterType.longValue()){//续租订单正常归还- 需要扣本次续租订单的租金
                BigDecimal orderAmount = artOrder.getOrderAmount();//订单金额
                compensationAmount =new BigDecimal(artOrderAfter.getCompensationAmount()).add(orderAmount) ;
                //补偿金额不能大于剩余金额
                /*if(compensationAmount.compareTo(rest_amountBig) > 0){
                    throw new RuntimeException("补偿金额大于冻结金额");
                }*/
            }
            //补偿金额不能大于剩余金额
           /* if(compensationAmount.compareTo(rest_amountBig) > 0){
                throw new RuntimeException("补偿金额大于冻结金额");
            }*/

            subtract =compensationAmount;

        }
        return subtract;


    }
    //计算退款金额
    @Override
    public BigDecimal getRefundAmount(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {

        //租赁订单的退款金额计算方式？
        //1.首先要判断当前订单是否是续租订单
        //如果是续租订单则退款金额为 0
        //如果是首单 那么退款金额就是 订单金额
        BigDecimal refundAmount = null;
        String parentOrderNo = artOrder.getParentOrderNo();

        if(StringUtil.isEmpty(parentOrderNo)){//如果没有父订单号，说明是首单
           // String rest_amount = artOrderService.getRest_amount(artOrder.getOrderNo());
            // BigDecimal freezeAmount = artOrder.getFreezeAmount();
           /* BigDecimal rest_amountBig = new BigDecimal(freezeAmount);//剩余金额*/

            BigDecimal compensationAmount =new BigDecimal(artOrderAfter.getCompensationAmount()) ;
            //补偿金额不能大于剩余金额
            /*if(compensationAmount.compareTo(freezeAmount) > 0){
                throw new RuntimeException("补偿金额大于商品金额");
            }*/
            BigDecimal orderAmount = artOrder.getOrderAmount();//订单金额
            //比较订单金额和补偿金额，如果补偿金额大于订单金额，则退款金额为 0
            BigDecimal subtract = new BigDecimal(0);
            if(compensationAmount.compareTo(orderAmount) > 0){
                subtract = new BigDecimal("0");

            }else{
                subtract = orderAmount.subtract(compensationAmount);
            }
            Long afterType = artOrderAfter.getAfterType();
            if(2 == afterType.longValue()){//首单正常归还-不退款
                subtract = new BigDecimal("0");

            }

            refundAmount =   subtract;
        }else{
            refundAmount = new BigDecimal("0");
        }
        return refundAmount;
    }
    //退款
    @Override
    public boolean refund(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        //将订单状态设置为退款
        updateOrderStatus(artOrderAfter,artOrder);
        // return  artOrderService.afterZmnRefund(artOrder.getOrderNo());
        artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_REFUNDING);//将售后订单设置为退款中
        artOrderAfterService.updateArtOrderAfter(artOrderAfter);
        return true;
    }
    //更新订单状态
    @Override
    public void updateOrderStatus(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        ArtOrder update = new ArtOrder();
        update.setOrderNo(artOrder.getOrderNo());
        update.setOrderStatus("7");// 订单状态 3-退款申请
        int i = artOrderMapper.updateByOrderNo(update);
    }
    //结算 : 购买和 租赁不同类型的订单执行不同的执行逻辑
    //deduct 扣除补偿金额
    //refund 退款
    public AjaxResult settle(ArtOrderAfter artOrderAfter, ArtOrder artOrder, boolean deduct, boolean refund) {
        if(!deduct){//扣除补偿金额失败
            artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_DEBIT_EXCEPTION);
            artOrderAfterService.updateArtOrderAfter(artOrderAfter);
            //将订单修改为追缴订单
            ArtOrder updateOrder = new ArtOrder();
            updateOrder.setOrderNo(artOrder.getOrderNo());
            updateOrder.setOrderStatus("88");//需要手动支付
            updateOrder.setRecoveryStatus("1");
            updateOrder.setAliTradeNo(artOrder.getOrderNo());
            updateOrder.setOrderAmount(new BigDecimal(artOrderAfter.getCompensationAmount()));
            updateOrder.setRecoveryReason("补偿金额扣除冻结金额失败,请及时支付");
            artOrderService.updateByOrderNo(updateOrder);
            artAfterLogService.createAfterLog(artOrderAfter.getPlatAfterNo(),
                    "补偿金额扣除冻结金额失败,转为追缴订单",
                    artOrderAfter.getUserId(),
                    IArtAfterLogService.SYSTEM_USER_TYPE_SYS,
                    IArtAfterLogService.ORDER_STATUS_FINISH);
            return AjaxResult.success();
        }
         if(!refund) {//如果没有执行退款,就直接解冻订单，如果执行了退款，会在退款的定时任务那边解冻订单
             ArtOrder sel = new ArtOrder();
             sel.setOrderNo(artOrder.getOrderNo());
             if(StringUtil.isNotEmpty(artOrder.getParentOrderNo())){//判断是不是子订单
                 sel.setOrderNo(artOrder.getParentOrderNo());
             }
             boolean flag = false;

             flag =  artOrderService.afterCompleteZmOrder(sel);

             if(!flag){
                 artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_SETTLEMENT_EXCEPTION);
                 artOrderAfterService.updateArtOrderAfter(artOrderAfter);
                 artAfterLogService.createAfterLog(artOrderAfter.getPlatAfterNo(),
                         "租赁订单售后解冻订单异常",
                         artOrderAfter.getUserId(),
                         IArtAfterLogService.SYSTEM_USER_TYPE_SYS,
                         IArtAfterLogService.ORDER_STATUS_FINISH);
                 return AjaxResult.error("租赁订单售后解冻订单异常");
             }else{
                 artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_FINISH);
                 artOrderAfterService.updateArtOrderAfter(artOrderAfter);
             }
             return AjaxResult.success();
         }


      return AjaxResult.success();
    }
    //重新解冻订单
    public void reSettle(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        ArtOrder sel = new ArtOrder();
        sel.setOrderNo(artOrder.getOrderNo());
        if(StringUtil.isNotEmpty(artOrder.getParentOrderNo())){//判断是不是子订单
            sel.setOrderNo(artOrder.getParentOrderNo());
        }
        boolean flag = false;
        flag =  artOrderService.afterCompleteZmOrder(sel);
        if(!flag){
            artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_SETTLEMENT_EXCEPTION);
            artOrderAfterService.updateArtOrderAfter(artOrderAfter);
            artAfterLogService.createAfterLog(artOrderAfter.getPlatAfterNo(),
                    "租赁订单售后解冻订单异常",
                    artOrderAfter.getUserId(),
                    IArtAfterLogService.SYSTEM_USER_TYPE_SYS,
                    IArtAfterLogService.ORDER_STATUS_FINISH);
        }else{
            artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_FINISH);
            artOrderAfterService.updateArtOrderAfter(artOrderAfter);
        }
    }
    @Override
    public void saveAfterRefundRecord(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        //保存售后记录
        artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_FINISH);
        artOrderAfterService.updateArtOrderAfter(artOrderAfter);
    }
    //扣除补偿金额
    public boolean deductCompensationAmount(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        //根据补偿金额扣除 冻结金额 todo
        boolean b = artOrderService.zmChargebacksCPAM(artOrderAfter.getCompensationAmount(), artOrder);
       /* if(!b) {
            artOrderAfter.setStatus(IArtAfterLogService.ORDER_STATUS_SETTLEMENT_EXCEPTION);
            artOrderAfter.setCompensationAmount(artOrderAfter.getCompensationAmount());
            artOrderAfterService.updateArtOrderAfter(artOrderAfter);
            //将订单修改为追缴订单

            artAfterLogService.createAfterLog(artOrderAfter.getPlatAfterNo(),
                    "补偿金额扣除冻结金额失败,转为追缴订单",
                    artOrderAfter.getUserId(),
                    IArtAfterLogService.SYSTEM_USER_TYPE_SYS,
                    IArtAfterLogService.ORDER_STATUS_FINISH);
            return false;
        }*/
        return b;
    }

    @Override
    public AjaxResult settle(ArtOrderAfter artOrderAfter, ArtOrder artOrder) {
        return null;
    }
}
